D			[0-9]
L			[a-zA-Z_]
H			[a-fA-F0-9]
E			[Ee][+-]?{D}+
FS			(f|F|l|L)
IS			(u|U|l|L)*

%{
#include <stdio.h>
#include "y.tab.h"
#include "system.h"
int linenumber=1;
void count();
char temp[100];
extern char *printcode;
%}

%%

[\n]			{ linenumber++; }
[ \t\r\v\a\f]+		{ count();}		/* Ignore escape character */
"auto"			{ count(); return(AUTO); }
"break"			{ count(); return(BREAK); }
"case"			{ count(); return(CASE); }
"char"			{ count(); return(CHAR); }
"const"			{ count(); return(CONST); }
"continue"		{ count(); return(CONTINUE); }
"default"		{ count(); return(DEFAULT); }
"do"			{ count(); return(DO); }
"double"		{ count(); return(DOUBLE); }
"else"			{ count(); return(ELSE); }
"enum"			{ count(); return(ENUM); }
"extern"		{ count(); return(EXTERN); }
"float"			{ count(); return(FLOAT); }
"for"			{ count(); return(FOR); }
"goto"			{ count(); return(GOTO); }
"if"			{ count(); return(IF); }
"int"			{ count(); return(INT); }
"long"			{ count(); return(LONG); }
"register"		{ count(); return(REGISTER); }
"return"		{ count(); return(RETURN); }
"short"			{ count(); return(SHORT); }
"signed"		{ count(); return(SIGNED); }
"sizeof"		{ count(); return(SIZEOF); }
"static"		{ count(); return(STATIC); }
"struct"		{ count(); return(STRUCT); }
"switch"		{ count(); return(SWITCH); }
"typedef"		{ count(); return(TYPEDEF); }
"union"			{ count(); return(UNION); }
"unsigned"		{ count(); return(UNSIGNED); }
"void"			{ count(); return(VOID); }
"volatile"		{ count(); return(VOLATILE); }
"while"			{ count(); return(WHILE); }

[a-zA-Z_\$][a-zA-Z0-9_\$]*	{ count(); 
				  yylval.string=(char *)malloc(strlen(yytext)*sizeof(char)+1);
				  strcpy(yylval.string,yytext);
				  return(IDENTIFIER);   
				}
[0-9][0-9]*[lL]?				{// integer and long integer
							int i=0,j=0;
//							printf("AAAAAAAAAAAA : %s \n",yytext);
							if(yytext[0] == '+' || yytext[0] == '-')
								i++;
							while(yytext[i] != '\0' && yytext[i] != 'l' && yytext[i]!= 'L'){
								temp[j] = yytext[i];
								i++;j++;
							}
							temp[j] = '\0';
							//printf(temp);		
							if(yytext[i] == '\0'){
								yylval.intValue = atoi(temp);
								if(yytext[0] == '-')
									yylval.intValue*= -1;
								//printf("Integer: %d\n",yylval.intValue);
								return(INTEGER);
							}
							
							yylval.longIntValue = atoi(temp);
							if(yytext[0] == '-')
									yylval.longIntValue*= -1;
							//printf("Long Integer: %ld",yylval.longIntValue);
							return(LONGINTEGER);
						}	

[0][xX][0-9a-fA-F]+[lL]? 	{// hexadecimal integer and hexa long integer
							int i=2,value=0;
							while(yytext[i] != '\0' && yytext[i] != 'l' && yytext[i]!= 'L'){
								if(yytext[i]>='0' && yytext[i] <='9')
										value=value*16+yytext[i]-'0';
								else if (yytext[i]>='a' && yytext[i]<='f')
									value= value*16+yytext[i]-'a'+10;
								else if (yytext[i]>='A' && yytext[i]<='F')
									value= value*16+yytext[i]-'F'+10;
							}
							yylval.longIntValue = yylval.intValue = value;
							if(yytext[i] == '\0'){
								//printf("Octal: %d\n",yylval.intValue);
								return(HEXADECIMAL);
							}
							//printf("Long Octal: %ld\n",yylval.longIntValue);
							return(LONGHEXADECIMAL);
						} 		
([0-9]+\.[0-9]*)([eE][-+]?[0-9]+)?[dD]? |
([0-9]*\.[0-9]+)([eE][-+]?[0-9]+)?[dD]?		{// decimal double point literals
							int i=0,j=0;
							while(yytext[i] != '\0' && yytext[i] != 'd' && yytext[i]!= 'D'){
								temp[j] = yytext[i];
								i++;j++;
							}
							temp[j] = '\0';
							yylval.doubleValue = atof(temp);
							//printf("Decimal Double: %f\n",yylval.doubleValue);
							return(DECIMALDOUBLE);
						}

([0-9]+\.[0-9]*)([eE][-+]?[0-9]+)?[fF]? |
([0-9]*\.[0-9]+)([eE][-+]?[0-9]+)?[fF]?	{// decimal floating point literals
							int i=0,j=0;
							if(yytext[0] == '+' || yytext[0] == '-')
								i++;
							while(yytext[i] != '\0' && yytext[i] != 'f' && yytext[i]!= 'F'){
								temp[j] = yytext[i];
								i++;j++;
							}
							temp[j] = '\0';
							yylval.floatValue = atof(temp);
							if(yytext[0] == '-')
									yylval.floatValue*= -1;
							//printf("Float: %f\n", yylval.floatValue);
							return(DECIMALFLOAT);
						}

[0-9]+([eE][-+]?[0-9]+)?[dD] |
[0-9]+([eE][-+]?[0-9]+)[dD]?		{// double point literals 
							int i=0,j=0;
							if(yytext[0] == '+' || yytext[0] == '-')
								i++;
							while(yytext[i] != '\0' && yytext[i] != 'd' && yytext[i]!= 'D'){
								temp[j] = yytext[i];
								i++;j++;
							}
							temp[j] = '\0';
							yylval.doubleValue = atof(temp);
							if(yytext[0] == '-')
									yylval.doubleValue*= -1;
							//printf("Double Literal: %f\n", yylval.doubleValue);
							return(DOUBLEVAL);
						}

[0-9]+([eE][-+]?[0-9]+)?[fF]		{// floating point literals 
							int i=0,j=0;
							if(yytext[0] == '+' || yytext[0] == '-')
								i++;
							while(yytext[i] != '\0' && yytext[i] != 'f' && yytext[i]!= 'F'){
								temp[j] = yytext[i];
								i++;j++;
							}
							temp[j] = '\0';
							yylval.floatValue = atof(temp);
							if(yytext[0] == '-')
									yylval.floatValue*= -1;
							//printf("Floating Point: %f\n", yylval.floatValue);
							return(FLOATVAL);
						}

[\'][^\\\'\"\n][\']				{// for handling normal character literals 
								yylval.charValue = yytext[1];
								//printf("Char: %c\n", yylval.charValue);
								return(CHARACTER);
						}
[\'][\\][nbtfrva\'\"\\\?0][\'] {// for handling std-esc character literals
								switch(yytext[2]){
									case 'n': yylval.charValue = '\n';
									case 'b': yylval.charValue = '\b';
									case 't': yylval.charValue = '\t';
									case 'f': yylval.charValue = '\f';
									case 'r': yylval.charValue = '\r';
									case 'v': yylval.charValue = '\v';
									case 'a': yylval.charValue = '\a';
									case '\'': yylval.charValue = '\'';
									case '\"': yylval.charValue = '\"';
									case '\\': yylval.charValue = '\\';
									case '?': yylval.charValue = '\?';
									case '0': yylval.charValue = '\0';
								}
								//printf("Escape char: \\%c\n", yylval.charValue);
								return(ESCAPECHAR);
						}

[\'][\\][x][0-9a-fA-F]{1,3}[\'] 		{// hexadecimal charater literals
							*yytext++;	//skip first inverted comma
							//copy len-1 to string. Skips last inverted comma.
							yylval.string = (char *)malloc(strlen(yytext)*sizeof(char));
							strncpy(yylval.string, yytext, strlen(yytext)-1);
							yylval.string[strlen(yytext)-1]='\0';
							//printf("Hex Char Literal %s\n",yylval.string);
							return(HEXLITERAL);
						}

[<\"]([^\n\"\\]|([\\][nbtfrva\'\"\\\?0]))*[\">]	{	// normal string
							*yytext++;	//skip first inverted comma
							//copy len-1 to string. Skips last inverted comma.
							yylval.string = (char *)malloc(strlen(yytext)*sizeof(char));
							strncpy(yylval.string, yytext, strlen(yytext)-1);
							yylval.string[strlen(yytext)-1]='\0';
							//printf("String: %s\n", yylval.string);
							return(STRING);
						}	


"..."			{ count(); return(ELLIPSIS); }
">>="			{ count(); return(RIGHT_ASSIGN); }
"<<="			{ count(); return(LEFT_ASSIGN); }
"+="			{ count(); return(ADD_ASSIGN); }
"-="			{ count(); return(SUB_ASSIGN); }
"*="			{ count(); return(MUL_ASSIGN); }
"/="			{ count(); return(DIV_ASSIGN); }
"%="			{ count(); return(MOD_ASSIGN); }
"&="			{ count(); return(AND_ASSIGN); }
"^="			{ count(); return(XOR_ASSIGN); }
"|="			{ count(); return(OR_ASSIGN); }
">>"			{ count(); return(RIGHT_OP); }
"<<"			{ count(); return(LEFT_OP); }
"++"			{ count(); return(INC_OP); }
"--"			{ count(); return(DEC_OP); }
"->"			{ count(); return(PTR_OP); }
"&&"			{ count(); return(AND_OP); }
"||"			{ count(); return(OR_OP); }
"<="			{ count(); return(LE_OP); }
">="			{ count(); return(GE_OP); }
"=="			{ count(); return(EQ_OP); }
"!="			{ count(); return(NE_OP); }
";"			{ count(); return(';'); }
("{"|"<%")		{ count(); return('{'); }
("}"|"%>")		{ count(); return('}'); }
","			{ count(); return(','); }
":"			{ count(); return(':'); }
"="			{ count(); return('='); }
"("			{ count(); return('('); }
")"			{ count(); return(')'); }
("["|"<:")		{ count(); return('['); }
("]"|":>")		{ count(); return(']'); }
"."			{ count(); return('.'); }
"&"			{ count(); return('&'); }
"!"			{ count(); return('!'); }
"~"			{ count(); return('~'); }
"-"			{ count(); return('-'); }
"+"			{ count(); return('+'); }
"*"			{ count(); return('*'); }
"/"			{ count(); return('/'); }
"%"			{ count(); return('%'); }
"<"			{ count(); return('<'); }
">"			{ count(); return('>'); }
"^"			{ count(); return('^'); }
"|"			{ count(); return('|'); }
"?"			{ count(); return('?'); }
.			{ printf("\nError : Stray %s in program on line %d\n",yytext,linenumber); }

%%

yywrap()
{
	return(1);
}

/*
comment()
{
	char c, c1;

loop:
	while ((c = input()) != '*' && c != 0)
		putchar(c);

	if ((c1 = input()) != '/' && c != 0)
	{
		unput(c1);
		goto loop;
	}

	if (c != 0)
		putchar(c1);
}

*/
int column = 0;

void count()
{
	int i;

	for (i = 0; yytext[i] != '\0'; i++)
		if (yytext[i] == '\n')
			column = 0;
		else if (yytext[i] == '\t')
			column += 8 - (column % 8);
		else
			column++;

	//ECHO;
}


/*int check_type()
{
/*
* pseudo code --- this is what it should check
*
*	if (yytext == type_name)
*		return(TYPE_NAME);
*
*	return(IDENTIFIER);
*/

/*
*	it actually will only return IDENTIFIER
*

	return(IDENTIFIER);
}*/

